#include<iostream>
#include<string>
#include<fstream>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2

/*程序中相关数据类型定义*/
typedef int Status; //Status 是函数返回值类型，其值是函数结果状态代码。
typedef struct  {
    string    num;//学号
    string    name;//姓名
    string  major;//专业
    string  password;//登录密码
} student;

typedef student ElemType; //ElemType 为数据元素类型

typedef struct LNode {
    ElemType data; //结点的数据域
    struct LNode *next; //结点的指针域
} LNode; //链表结点类型

typedef LNode * LinkList;//单链表类型定义

Status InitList_L(LinkList & L)//初始化空链表 
{
    L = new LNode;
    L->next = nullptr;
    return OK;
} 

LNode* LocateElem_P(LinkList L, string stu_num) { //修改按照学号查找，返回结点指针 
    LNode *p = L->next;
    while (p != nullptr && p->data.num != stu_num) {
        p = p->next;
    }
    return p;
} //LocateElem_P

int LocateElem(LinkList L, string stu_num) { //修改按照学号查找，返回位序 
    int i = 0;
    LNode *p = L->next;
    while (p != nullptr) {
        i++;
        if (p->data.num == stu_num) {
            return i;
        }
        p = p->next;
    }
    return 0;
} //LocateElem

Status ListInsert_L(LinkList &L, int i, ElemType e) { //算法2.9 单链表的插入
    if (i < 1) return ERROR;
    LNode *p = L;
    int j = 0;
    while (p != nullptr && j < i - 1) {
        p = p->next;
        j++;
    }
    if (p == nullptr) return ERROR; // i值不合法
    LNode *s = new LNode;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
} //ListInsert_L

Status ListDelete_L(LinkList &L, int i) { //算法2.10 单链表的删除位序为i的元素
    if (i < 1) return ERROR;
    LNode *p = L;
    int j = 0;
    while (p->next != nullptr && j < i - 1) {
        p = p->next;
        j++;
    }
    if (p->next == nullptr) return ERROR; // i值不合法
    LNode *q = p->next;
    p->next = q->next;
    delete q;
    return OK;
} //ListDelete_L

 //输入n个用户信息，完成链表L构建。
void CreatList(LinkList &L,int n)
{
    int i;
    ElemType e;
    InitList_L(L);
    for(i=1;i<=n;i++)
    {
        cin >> e.num>> e.name>> e.major>> e.password;
        ListInsert_L(L,i,e);
    }
}
void op_user_menu()
{
    cout<<endl;
    cout<<"/***********************输入数字进行操作选择************************/"<<endl;
    cout<<"1.注册"<<endl;
    cout<<"2.登录"<<endl;
    cout<<"3.输入学号修改登录密码"<<endl;
    cout<<"4.输入学号进行账号注销"<<endl;
    cout<<"5.显示所有学生信息"<<endl;
    cout<<"0.保存并退出程序，"<<endl;
    cout<<endl;
    return ;
}

void Register(LinkList &L)//输入学生学号、姓名、专业、登录密码完成注册。具体功能看前面描述
{
    ElemType e;
    cout << "输入以下信息进行注册" << endl;
    cout << "学号：" << endl;
    cin >> e.num;
    if (LocateElem(L, e.num) != 0) {
        cout << "账号已存在，重新输入" << endl;
        return;
    }
    cout << "姓名：" << endl;
    cin >> e.name;
    cout << "专业：" << endl;
    cin >> e.major;
    cout << "密码：" << endl;
    cin >> e.password;
    string password_confirm;
    cout << "再次输入密码:" << endl;
    cin >> password_confirm;
    while (e.password != password_confirm) {
        cout << "两次密码不一致，重新输入：" << endl;
        cin >> e.password;
        cout << "再次输入密码:" << endl;
        cin >> password_confirm;
    }
    ListInsert_L(L, 1, e);
    cout << "注册成功" << endl;
}

void Log_in(LinkList L)//输入学号、密码进行验证登录，具体功能看前面描述
{
    string stu_num, password;
    cout << "输入学号和密码进行登录" << endl;
    cout << "学号：" << endl;
    cin >> stu_num;
    cout << "密码：" << endl;
    cin >> password;
    LNode *p = LocateElem_P(L, stu_num);
    if (p != nullptr && p->data.password == password) {
        cout << "登录成功" << endl;
    } else {
        cout << "账号密码错误" << endl;
    }
}

void Log_out(LinkList &L)//输入学号，进行注销用户。具体功能看前面描述
{
    string stu_num, confirm_stu_num;
    cout << "输入学号进行注销" << endl;
    cout << "学号：" << endl;
    cin >> stu_num;
    LNode *p = LocateElem_P(L, stu_num);
    if (p == nullptr) {
        cout << "该用户不存在" << endl;
        return;
    }
    cout << "再次输入学号确认" << endl;
    cin >> confirm_stu_num;
    if (confirm_stu_num != stu_num) {
        cout << "两次学号错误" << endl;
        return;
    }
    int position = LocateElem(L, stu_num);
    ListDelete_L(L, position);
    cout << "注销账号成功" << endl;
}

void Modify_Password(LinkList &L)
{
    string stu_num, new_password, confirm_password;
    cout << "输入学号进行信息修改" << endl;
    cout << "学号：" << endl;
    cin >> stu_num;
    LNode *p = LocateElem_P(L, stu_num);
    if (p == nullptr) {
        cout << "该用户不存在" << endl;
        return;
    }
    cout << "新密码：" << endl;
    cin >> new_password;
    cout << "再次输入新密码：" << endl;
    cin >> confirm_password;
    while (new_password != confirm_password) {
        cout << "两次密码不一致" << endl;
        cout << "新密码：" << endl;
        cin >> new_password;
        cout << "再次输入新密码：" << endl;
        cin >> confirm_password;
    }
    p->data.password = new_password;
    cout << "密码修改成功" << endl;
}

void PrintList(LinkList L) //按行输出用户的学号、姓名、专业，用空格隔开。输出所有用户信息后再换一行
{
    LNode *p = L->next;
    while (p != nullptr) {
        cout << p->data.num << " " << p->data.name << " " << p->data.major << endl;
        p = p->next;
    }
    cout << endl;
}
// 将文件中的数据写入到L
void File_in_List(LinkList& L) {
    student e;
    fstream file;
    InitList_L(L);
    int i = 1;
    file.open("student.txt");
    if (!file) {
        cout << "错误！未找到文件！" << endl;
        exit(ERROR);
    }
    while (!file.eof()) {
        file >> e.num >> e.name >> e.major >> e.password;
        ListInsert_L(L, i, e);
        i++;
    }
    cout << "输入 student.txt 信息完毕" << endl << endl;
    file.close();
}
// 表L的数据写回文件student.txt
void List_out_file(LinkList L) {
    LNode* p;
    student e;
    fstream file("student.txt", fstream::out | ios_base::trunc); // 打开时清空文件
    if (!file) {
        cout << "错误！未找到文件！" << endl;
        exit(ERROR);
    }
    p = L->next;
    while (p->next) {
        e = p->data;
        file << left << e.num << "\t" << left << e.name << "\t" << left << e.major << "\t" << left << e.password << endl;
        p = p->next;
    }
    if (p) // 最后一个元素写入不要换行
    {
        e = p->data;
        file << left << e.num << "\t" << left << e.name << "\t" << left << e.major << "\t" << left << e.password;
    }

    file.close();
}
int main() {

    LinkList L;//定义单链表变量L
    int op,n;
    cin>>n;
    // CreatList(L,n);
    File_in_List(L); // 导入用户数据到表L
    while(1)
    {
        op_user_menu();
        cin>>op;
        switch (op)
        {
        case 1:  //输入1，注册功能
            Register(L);
            break;
        case 2:
            Log_in(L); //输入2，登录功能
            break;
        case 3:     //输入3，修改密码功能
            Modify_Password(L);
            break;
        case 4:       //输入4，注销用户功能
            Log_out(L);
            break;
        case 5:           //输入5，显示所有用户信息
            PrintList(L);
            break;
        case 0:
            List_out_file(L);
            return 0;
        default:;
        }
    }

    return 0;

}
